#pragma once

#include <vector>
#include <queue>
#include <thread>
#include <memory>
#include <atomic>
#include "Log.hpp"
#include "Cond.hpp"
#include "Mutex.hpp"

namespace ThreadPoolModule
{
    using namespace MutexModule;
    using namespace CondModule;
    using namespace LogModule;

    const int gnum = 5; // 线程个数

    template <typename T>
    class ThreadPool
    {
    private:
        ThreadPool(int num = gnum)
            : _num(num), _sleep_num(0), _running(true)
        {
            for (int i = 0; i < _num; ++i)
            {
                // 隐式使用了this，在成员函数内部默认是this->HandlerTask()
                _threads.emplace_back([this]()
                                      { HandlerTask(); });
            }
        }
        ThreadPool(const ThreadPool &) = delete;
        ThreadPool &operator=(const ThreadPool &) = delete;

    public:
        static ThreadPool *GetInstance()
        {
            if (_inc == nullptr)
            {
                LockGuard lockguard(_inc_mutex);
                if (_inc == nullptr)
                {
                    LOG(LogLevel::DEBUG) << "首次使用单例, 创建之....";
                    // _inc = std::make_unique<ThreadPool>();
                    // std::make_unique 是一个外部函数，无法访问 ThreadPool 类的私有构造函数
                    _inc.reset(new ThreadPool());
                }
            }

            LOG(LogLevel::DEBUG) << "获取单例";
            return _inc.get(); // 返回原始指针，不转移所有权
        }

        void HandlerTask()
        {
            while (true)
            {
                T task;
                {
                    LockGuard lockguard(_tasks_mutex);
                    while (_tasks.empty() && _running)
                    {
                        ++_sleep_num;
                        _tasks_cond.Wait(_tasks_mutex);
                        --_sleep_num;
                    }

                    if (_tasks.empty() && !_running)
                        break;

                    task = _tasks.front();
                    _tasks.pop();
                }
                task();
            }
        }

        void Enqueue(const T &task)
        {
            if (_running)
            {
                LockGuard lockguard(_tasks_mutex);
                if (_running)
                {
                    _tasks.push(task);
                    if (_sleep_num == _num)
                    {
                        LOG(LogLevel::INFO) << "唤醒一个休眠线程";
                        _tasks_cond.Signal();
                    }
                }
            }
        }

        void Stop()
        {
            if (!_running)
                return;

            _running = false;

            if (_sleep_num)
            {
                LOG(LogLevel::INFO) << "唤醒所有休眠线程";
                _tasks_cond.Broadcast();
            }
        }

        void Join()
        {
            LOG(LogLevel::INFO) << "join所有线程";
            for (auto &thread : _threads)
            {
                if (thread.joinable())
                    thread.join();
            }
        }

    private:
        std::vector<std::thread> _threads;
        int _num;       // 线程个数
        int _sleep_num; // 线程阻塞个数

        std::queue<T> _tasks;
        Mutex _tasks_mutex;
        Cond _tasks_cond;

        static std::unique_ptr<ThreadPool> _inc;
        std::atomic<bool> _running; // 线程池是否启动。
        static Mutex _inc_mutex;
    };

    template <typename T>
    std::unique_ptr<ThreadPool<T>> ThreadPool<T>::_inc = nullptr;

    template <typename T>
    Mutex ThreadPool<T>::_inc_mutex;
}